package com.yugao.fintech.antelope.base.model.module.config.param;

import com.yugao.fintech.antelope.base.model.constants.RequestCons;
import com.yugao.fintech.antelope.base.model.constants.ValidationCons;
import com.yugao.fintech.framework.assistant.utils.StringUtils;
import com.yugao.fintech.framework.assistant.utils.exception.BizException;
import com.yugao.fintech.framework.desensitization.annotations.FieldSensitive;
import com.yugao.fintech.framework.desensitization.fieldsensitive.enums.StrategyType;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.validator.constraints.URL;
import org.springframework.stereotype.Component;

import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 文件存储配置配置参数

 */
@Getter
@Setter
@Component
public abstract class StorageParam<T extends StorageParam<T>> extends BaseConfigParam<T> {
    /**
     * 桶名, 请保证bucket为可公共读取的
     */
    @NotEmpty(message = ValidationCons.NOT_EMPTY)
    protected String bucket;

    /**
     * 私有桶, 可选
     */
    protected String privateBucket;

    @NotEmpty(message = ValidationCons.NOT_EMPTY)
    @FieldSensitive(StrategyType.RESERVE_4)
    protected String accessKey;

    @NotEmpty(message = ValidationCons.NOT_EMPTY)
    @FieldSensitive(StrategyType.RESERVE_4)
    protected String secretKey;

    /**
     * 端点
     */
    @URL(message = "地址有误")
    protected String endpoint;


    /**
     * 访问域名
     */
    @NotNull(message = ValidationCons.NOT_EMPTY)
    private List<Domain> domains = new ArrayList<>();

    /**
     * 检查自定义的域名
     * 端点值要唯一
     */
    @Override
    protected void customValidate() {
        Map<String, List<Domain>> map = this.domains.stream()
                .peek(e -> e.setEndpointValue(Optional.ofNullable(e.getEndpointValue()).orElse("")))
                .collect(Collectors.groupingBy(Domain::getEndpointValue));
        map.forEach((k, v) -> {
            if (v.size() > 1) {
                throw new BizException("{} 端点值重复", StringUtils.isEmpty(k) ? "默认" : k);
            }
        });
    }

    /**
     * 自定义域名
     */
    @Data
    public static class Domain implements Serializable {
        /**
         * 如果请求头中 {@link RequestCons.Headers#ORIGIN_ENDPOINT} 的值和当前字段值一样, 则采用当前对象配置的
         * 域名(domain)
         *
         * @see RequestCons.Headers#ORIGIN_ENDPOINT
         */
        private String endpointValue = "";

        /**
         * 域名
         */
        @URL(message = "域名地址有误")
        private String domain;
    }
}
